home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v2.1 / Amiga Developer CD v2.1.iso / Contributions / Haage_&_Partner / Storm-Projects / NDKExamples1 / intuition / attachdemo.c < prev    next >
C/C++ Source or Header  |  1999-04-16  |  19KB  |  917 lines

  1. /*
  2.  * attachdemo.c - demonstrates handling attached screens
  3.  *
  4.  * (c) Copyright 1992-1996 Amiga International, Inc. All rights reserved.
  5.  *
  6.  * This software is provided as-is and is subject to change; no warranties
  7.  * are made.  All use is at your own risk.  No liability or responsibility
  8.  * is assumed.
  9.  *
  10.  */
  11.  
  12. /*----------------------------------------------------------------------*/
  13.  
  14. #include <exec/types.h>
  15. #include <graphics/displayinfo.h>
  16. #include <graphics/gfxbase.h>
  17. #include <intuition/intuition.h>
  18. #include <intuition/intuitionbase.h>
  19.  
  20. #include <clib/exec_protos.h>
  21. #include <clib/graphics_protos.h>
  22. #include <clib/intuition_protos.h>
  23. #include <clib/gadtools_protos.h>
  24.  
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27.  
  28. /*----------------------------------------------------------------------*/
  29.  
  30. struct ScreenDescriptor
  31. {
  32.     LONG sd_Top;    /* Top edge in non-lace coords */
  33.     LONG sd_Open;    /* If screen is supposed to be open */
  34.     LONG sd_Lace;    /* If screen is supposed to be lace */
  35.     LONG sd_Size;    /* Screen's intended size (see below) */
  36.     LONG sd_Drag;    /* If screen is supposed to be draggable */
  37.     LONG sd_IsLace;    /* If screen was actually last lace */
  38. };
  39.  
  40. #define SIZE_NORMAL    0
  41. #define SIZE_TALL    1
  42. #define SIZE_WIDE    2
  43. #define SIZE_HUGE    3
  44.  
  45. /*----------------------------------------------------------------------*/
  46.  
  47. void error_exit( STRPTR errorstring );
  48. void CloseWindowSafely( struct Window *win );
  49. void StripIntuiMessages( struct MsgPort *mp, struct Window *win );
  50. struct Screen *findPanelScreen( void );
  51. struct Window *openPanel( void );
  52. void closePanel( void );
  53. void handleGadget( struct Gadget *gad, UWORD code );
  54. void jiggleScreen( struct Screen *sc, ULONG flags );
  55.  
  56. /*----------------------------------------------------------------------*/
  57.  
  58. struct Library *GfxBase = NULL;
  59. struct Library *IntuitionBase = NULL;
  60. struct Library *GadToolsBase = NULL;
  61. struct MsgPort *sharedport = NULL;
  62. void *panel_vi = NULL;
  63. struct Gadget *panel_gadgets = NULL;
  64. struct Window *panel_win = NULL;
  65. struct Screen *panel_screen = NULL;
  66.  
  67. struct Screen *parent_sc = NULL;
  68. struct Screen *child_sc = NULL;
  69. struct ScreenDescriptor parent_desc =
  70. {
  71.     0,            /* sd_Top */
  72.     FALSE,        /* sd_Open */
  73.     FALSE,        /* sd_Lace */
  74.     SIZE_NORMAL,    /* sd_Size */
  75.     TRUE,        /* sd_Drag */
  76. };
  77.  
  78. struct ScreenDescriptor child_desc =
  79. {
  80.     80,            /* sd_Top */
  81.     TRUE,        /* sd_Open */
  82.     FALSE,        /* sd_Lace */
  83.     SIZE_NORMAL,    /* sd_Size */
  84.     TRUE,        /* sd_Drag */
  85. };
  86.  
  87. /*----------------------------------------------------------------------*/
  88.  
  89. struct TextAttr Topaz80 =
  90. {
  91.     "topaz.font",
  92.     8,
  93.     FS_NORMAL,
  94.     FPF_DESIGNED|FPF_ROMFONT,
  95. };
  96.  
  97. /*----------------------------------------------------------------------*/
  98.  
  99. #define CHILD_MAGIC    ( (APTR)0x0FACE0FF )
  100. #define PARENT_MAGIC    ( (APTR)0x8FACE0FF )
  101.  
  102. #define GAD_PARENT_OPEN    0    /* settable */
  103. #define GAD_PARENT_LACE    1
  104. #define GAD_PARENT_SIZE    2
  105. #define GAD_PARENT_DRAG    3
  106.  
  107. #define GAD_CHILD_OPEN    4    /* settable */
  108. #define GAD_CHILD_LACE    5
  109. #define GAD_CHILD_SIZE    6
  110. #define GAD_CHILD_DRAG    7
  111.  
  112. #define GAD_FORWARD    8
  113. #define GAD_BACK    9
  114. #define GAD_CFORWARD    10
  115. #define GAD_CBACK    11
  116.  
  117. #define GAD_MOVEPARENT    12
  118. #define GAD_MOVECHILD    13
  119. #define GAD_FMOVEPARENT    14
  120. #define GAD_FMOVECHILD    15
  121.  
  122. #define GAD_HOMEPARENT    16
  123. #define GAD_HOMECHILD    17
  124.  
  125. #define NUM_SETTABLE    2
  126.  
  127. struct Gadget *mygad[ NUM_SETTABLE ];
  128.  
  129. UWORD pens[] =
  130. {
  131.     0, /* DETAILPEN */
  132.     1, /* BLOCKPEN    */
  133.     1, /* TEXTPEN    */
  134.     2, /* SHINEPEN    */
  135.     1, /* SHADOWPEN    */
  136.     3, /* FILLPEN    */
  137.     1, /* FILLTEXTPEN    */
  138.     0, /* BACKGROUNDPEN    */
  139.     2, /* HIGHLIGHTTEXTPEN    */
  140.  
  141.     1, /* BARDETAILPEN    */
  142.     2, /* BARBLOCKPEN    */
  143.     1, /* BARTRIMPEN    */
  144.  
  145.     (UWORD)~0,
  146. };
  147.  
  148. /*----------------------------------------------------------------------*/
  149.  
  150. STRPTR OpenLabels[] =
  151. {
  152.     "Closed",
  153.     "Open",
  154.     NULL,
  155. };
  156.  
  157. STRPTR LaceLabels[] =
  158. {
  159.     "Non-Laced",
  160.     "Interlaced",
  161.     NULL,
  162. };
  163.  
  164. STRPTR SizeLabels[] =
  165. {
  166.     "Normal",
  167.     "Tall",
  168.     "Wide",
  169.     "Huge",
  170.     NULL,
  171. };
  172.  
  173. STRPTR DragLabels[] =
  174. {
  175.     "Non-Drag",
  176.     "Draggable",
  177.     NULL,
  178. };
  179.  
  180. LONG scwidth[ 4 ] =
  181. {
  182.     640, 640, 960, 960,    /* normal, tall, wide, huge */
  183. };
  184.  
  185. LONG cheight[ 4 ] =
  186. {
  187.  
  188.     120, 380, 120, 380,    /* normal, tall, wide, huge */
  189. };
  190.  
  191. LONG pheight[ 4 ] =
  192. {
  193.  
  194.     200, 400, 200, 400,    /* normal, tall, wide, huge */
  195. };
  196.  
  197. /*----------------------------------------------------------------------*/
  198.  
  199. struct Screen *
  200. openMyScreen( BOOL isparent )
  201. {
  202.     struct Screen *sc;
  203.     LONG top, drag, width, height, id;
  204.     STRPTR title;
  205.     ULONG attachtag;
  206.     APTR userdata;
  207.     struct Screen *attachdata = NULL;
  208.  
  209.     if ( isparent )
  210.     {
  211.     top = parent_desc.sd_Top;
  212.     drag = parent_desc.sd_Drag;
  213.     width = scwidth[ parent_desc.sd_Size ];
  214.     if ( parent_desc.sd_Lace )
  215.     {
  216.         title = "Laced Parent";
  217.         height = 2*pheight[ parent_desc.sd_Size ];
  218.         top *= 2;
  219.         id = HIRESLACE_KEY;
  220.     }
  221.     else
  222.     {
  223.         title = "Non-laced Parent";
  224.         height = pheight[ parent_desc.sd_Size ];
  225.         id = HIRES_KEY;
  226.     }
  227.     attachtag = SA_FrontChild;
  228.     attachdata = child_sc;
  229.     userdata = CHILD_MAGIC;
  230.     }
  231.     else
  232.     {
  233.     top = child_desc.sd_Top;
  234.     drag = child_desc.sd_Drag;
  235.     width = scwidth[ child_desc.sd_Size ];
  236.     if ( child_desc.sd_Lace )
  237.     {
  238.         title = "Laced Child";
  239.         height = cheight[ child_desc.sd_Size ]*2;
  240.         top *= 2;
  241.         id = HIRESLACE_KEY;
  242.     }
  243.     else
  244.     {
  245.         title = "Non-laced Child";
  246.         height = cheight[ child_desc.sd_Size ];
  247.         id = HIRES_KEY;
  248.     }
  249.     attachtag = SA_Parent;
  250.     attachdata = parent_sc;
  251.     userdata = PARENT_MAGIC;
  252.     }
  253.  
  254.     if ( sc = OpenScreenTags( NULL,
  255.     SA_DisplayID, id,
  256.     SA_Top, top,
  257.     SA_Title, title,
  258.     SA_Width, width,
  259.     SA_Height, height,
  260.     SA_Overscan, OSCAN_TEXT,
  261.     /*  Other tags can go here: */
  262.     SA_Depth, 2,
  263.     SA_Pens, pens,
  264.     SA_Draggable, drag,
  265.     SA_AutoScroll, TRUE,
  266.     SA_Font, &Topaz80,
  267.     attachtag, attachdata,
  268.     TAG_DONE ) )
  269.     {
  270.     sc->UserData = userdata;
  271.     }
  272.     return( sc );
  273. }
  274.  
  275. struct Screen *
  276. closeMyScreen( struct Screen *sc )
  277. {
  278.     if ( sc )
  279.     {
  280.     if ( panel_screen == sc )
  281.     {
  282.         closePanel();
  283.     }
  284.     CloseScreen( sc );
  285.     }
  286.     return( ( struct Screen * )NULL );
  287. }
  288.  
  289. /*----------------------------------------------------------------------*/
  290.  
  291. void
  292. main( void )
  293.  
  294. {
  295.     BOOL done = FALSE;
  296.     struct IntuiMessage *imsg;
  297.     ULONG imsgClass;
  298.     UWORD imsgCode;
  299.     APTR imsgIAddress;
  300.  
  301.     if ( !( GfxBase = 
  302.     OpenLibrary( "graphics.library", 39L ) ) )
  303.     {
  304.     error_exit( "Couldn't open Gfx V39\n" );
  305.     }
  306.  
  307.     if ( !( IntuitionBase = 
  308.     OpenLibrary( "intuition.library", 39L ) ) )
  309.     {
  310.     error_exit( "Couldn't open Intuition V39\n" );
  311.     }
  312.  
  313.     if ( !( GadToolsBase =
  314.     OpenLibrary( "gadtools.library", 39L ) ) )
  315.     {
  316.     error_exit( "Couldn't open GadTools V39\n" );
  317.     }
  318.  
  319.     if ( !( sharedport = CreateMsgPort() ) )
  320.     {
  321.     error_exit( "No port\n" );
  322.     }
  323.  
  324.     if ( child_desc.sd_Open )
  325.     {
  326.     child_sc = openMyScreen( FALSE );
  327.     child_desc.sd_IsLace = child_desc.sd_Lace;
  328.     }
  329.  
  330.     if ( parent_desc.sd_Open )
  331.     {
  332.     parent_sc = openMyScreen( TRUE );
  333.     parent_desc.sd_IsLace = parent_desc.sd_Lace;
  334.     }
  335.  
  336.     openPanel();
  337.  
  338.     while ( !done )
  339.     {
  340.     Wait( 1 << sharedport->mp_SigBit );
  341.     while ( imsg = GT_GetIMsg( sharedport ) )
  342.     {
  343.         imsgClass = imsg->Class;
  344.         imsgCode = imsg->Code;
  345.         imsgIAddress = imsg->IAddress;
  346.         GT_ReplyIMsg( imsg );
  347.  
  348.         switch ( imsgClass )
  349.         {
  350.         case IDCMP_CLOSEWINDOW:
  351.             done = TRUE;
  352.             break;
  353.  
  354.         case IDCMP_REFRESHWINDOW:
  355.             /* Only the panel-window has IDCMP_REFRESHWINDOW set */
  356.             GT_BeginRefresh( panel_win );
  357.             GT_EndRefresh( panel_win, TRUE );
  358.             break;
  359.  
  360.         case IDCMP_GADGETUP:
  361.             handleGadget( imsgIAddress, imsgCode );
  362.             break;
  363.         }
  364.     }
  365.     }
  366.     error_exit( NULL );
  367. }
  368.  
  369.  
  370. /*----------------------------------------------------------------------*/
  371.  
  372. void error_exit( STRPTR errorstring )
  373.  
  374. {
  375.     closePanel();
  376.  
  377.     closeMyScreen( child_sc );
  378.  
  379.     closeMyScreen( parent_sc );
  380.  
  381.     if ( sharedport )
  382.     {
  383.     DeleteMsgPort( sharedport );
  384.     }
  385.  
  386.     if ( GadToolsBase )
  387.     {
  388.     CloseLibrary( GadToolsBase );
  389.     }
  390.  
  391.     if ( IntuitionBase )
  392.     {
  393.     CloseLibrary( IntuitionBase );
  394.     }
  395.  
  396.     if ( GfxBase )
  397.     {
  398.     CloseLibrary( GfxBase );
  399.     }
  400.  
  401.     if ( errorstring )
  402.     {
  403.     printf( errorstring );
  404.     exit( 20 );
  405.     }
  406.  
  407.     exit( 0 );
  408. }
  409.  
  410.  
  411. /*----------------------------------------------------------------------*/
  412.  
  413. /* these functions close an Intuition window
  414.  * that shares a port with other Intuition
  415.  * windows or IPC customers.
  416.  *
  417.  * We are careful to set the UserPort to
  418.  * null before closing, and to free
  419.  * any messages that it might have been
  420.  * sent.
  421.  */
  422.  
  423. void CloseWindowSafely( struct Window *win)
  424. {
  425.     /* we forbid here to keep out of race conditions with Intuition */
  426.     Forbid();
  427.  
  428.     /* send back any messages for this window
  429.      * that have not yet been processed
  430.      */
  431.     StripIntuiMessages( win->UserPort, win );
  432.  
  433.     /* clear UserPort so Intuition will not free it */
  434.     win->UserPort = NULL;
  435.  
  436.     /* tell Intuition to stop sending more messages */
  437.     ModifyIDCMP( win, 0L );
  438.  
  439.     /* turn multitasking back on */
  440.     Permit();
  441.  
  442.     /* and really close the window */
  443.     CloseWindow( win );
  444. }
  445.  
  446. /* remove and reply all IntuiMessages on a port that
  447.  * have been sent to a particular window
  448.  * ( note that we don't rely on the ln_Succ pointer
  449.  *  of a message after we have replied it )
  450.  */
  451. void StripIntuiMessages( struct MsgPort *mp, struct Window *win)
  452. {
  453.     struct IntuiMessage *msg;
  454.     struct Node *succ;
  455.  
  456.     msg = ( struct IntuiMessage * ) mp->mp_MsgList.lh_Head;
  457.  
  458.     while( succ =  msg->ExecMessage.mn_Node.ln_Succ ) {
  459.  
  460.     if( msg->IDCMPWindow ==  win ) {
  461.  
  462.         /* Intuition is about to free this message.
  463.          * Make sure that we have politely sent it back.
  464.          */
  465.         Remove( ( struct Node * )msg );
  466.  
  467.         ReplyMsg( ( struct Message * )msg );
  468.     }
  469.  
  470.     msg = ( struct IntuiMessage * ) succ;
  471.     }
  472. }
  473.  
  474. /*----------------------------------------------------------------------*/
  475.  
  476. struct Window *openPanel( void )
  477. {
  478.     struct NewGadget ng;
  479.     struct Gadget *gad;
  480.     LONG topborder;
  481.     int settable = 0;
  482.  
  483.     panel_screen = findPanelScreen();
  484.  
  485.     topborder = panel_screen->WBorTop + panel_screen->Font->ta_YSize + 1;
  486.  
  487.     if ( panel_vi = GetVisualInfo( panel_screen,
  488.     TAG_DONE ) )
  489.     {
  490.     gad = CreateContext( &panel_gadgets );
  491.  
  492.     ng.ng_LeftEdge = 90;
  493.     ng.ng_TopEdge = 2+topborder;
  494.     ng.ng_GadgetText = "Parent";
  495.     ng.ng_Width = 120;
  496.     ng.ng_Height = 14;
  497.     ng.ng_TextAttr = &Topaz80;
  498.     ng.ng_VisualInfo = panel_vi;
  499.     ng.ng_GadgetID = GAD_PARENT_OPEN;
  500.     ng.ng_UserData = &parent_desc.sd_Open;
  501.     ng.ng_Flags = NULL;
  502.  
  503.     mygad[ settable++ ] = gad = CreateGadget( CYCLE_KIND, gad, &ng,
  504.         GTCY_Labels, OpenLabels,
  505.         GTCY_Active, parent_desc.sd_Open,
  506.         TAG_DONE );
  507.     ng.ng_GadgetText = NULL;
  508.     ng.ng_UserData = 0;
  509.  
  510.     ng.ng_LeftEdge += 130;
  511.     ng.ng_GadgetID++;
  512.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  513.         GTCY_Labels, LaceLabels,
  514.         GTCY_Active, parent_desc.sd_Lace,
  515.         TAG_DONE );
  516.  
  517.     ng.ng_LeftEdge += 130;
  518.     ng.ng_GadgetID++;
  519.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  520.         GTCY_Labels, SizeLabels,
  521.         GTCY_Active, parent_desc.sd_Size,
  522.         TAG_DONE );
  523.  
  524.     ng.ng_LeftEdge += 130;
  525.     ng.ng_GadgetID++;
  526.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  527.         GTCY_Labels, DragLabels,
  528.         GTCY_Active, parent_desc.sd_Drag,
  529.         TAG_DONE );
  530.  
  531.     ng.ng_LeftEdge = 90;
  532.     ng.ng_TopEdge += 18;
  533.     ng.ng_GadgetText = "Child";
  534.     ng.ng_GadgetID++;
  535.     ng.ng_UserData = &child_desc.sd_Open;
  536.  
  537.     mygad[ settable++ ] = gad = CreateGadget( CYCLE_KIND, gad, &ng,
  538.         GTCY_Labels, OpenLabels,
  539.         GTCY_Active, child_desc.sd_Open,
  540.         TAG_DONE );
  541.     ng.ng_GadgetText = NULL;
  542.     ng.ng_UserData = NULL;
  543.  
  544.     ng.ng_LeftEdge += 130;
  545.     ng.ng_GadgetID++;
  546.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  547.         GTCY_Labels, LaceLabels,
  548.         GTCY_Active, child_desc.sd_Lace,
  549.         TAG_DONE );
  550.  
  551.     ng.ng_LeftEdge += 130;
  552.     ng.ng_GadgetID++;
  553.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  554.         GTCY_Labels, SizeLabels,
  555.         GTCY_Active, child_desc.sd_Size,
  556.         TAG_DONE );
  557.  
  558.     ng.ng_LeftEdge += 130;
  559.     ng.ng_GadgetID++;
  560.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  561.         GTCY_Labels, DragLabels,
  562.         GTCY_Active, child_desc.sd_Drag,
  563.         TAG_DONE );
  564.  
  565.     ng.ng_LeftEdge = 90;
  566.     ng.ng_TopEdge += 18;
  567.     ng.ng_GadgetText = "Forward";
  568.     ng.ng_GadgetID++;
  569.     ng.ng_UserData = SDEPTH_TOFRONT;
  570.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  571.         TAG_DONE );
  572.  
  573.     ng.ng_LeftEdge += 130;
  574.     ng.ng_GadgetText = "Back";
  575.     ng.ng_GadgetID++;
  576.     ng.ng_UserData = ( APTR )( SDEPTH_TOBACK );
  577.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  578.         TAG_DONE );
  579.  
  580.     ng.ng_LeftEdge += 130;
  581.     ng.ng_GadgetText = "Child Forward";
  582.     ng.ng_GadgetID++;
  583.     ng.ng_UserData = ( APTR )( SDEPTH_TOFRONT|SDEPTH_CHILDONLY );
  584.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  585.         TAG_DONE );
  586.  
  587.     ng.ng_LeftEdge += 130;
  588.     ng.ng_GadgetText = "Child Back";
  589.     ng.ng_GadgetID++;
  590.     ng.ng_UserData = ( APTR )( SDEPTH_TOBACK|SDEPTH_CHILDONLY );
  591.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  592.         TAG_DONE );
  593.  
  594.     ng.ng_LeftEdge = 90;
  595.     ng.ng_TopEdge += 18;
  596.     ng.ng_GadgetText = "Move Parent";
  597.     ng.ng_GadgetID++;
  598.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  599.         TAG_DONE );
  600.  
  601.     ng.ng_LeftEdge += 130;
  602.     ng.ng_GadgetText = "Move Child";
  603.     ng.ng_GadgetID++;
  604.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  605.         TAG_DONE );
  606.  
  607.     ng.ng_LeftEdge += 130;
  608.     ng.ng_GadgetText = "FMove Parent";
  609.     ng.ng_GadgetID++;
  610.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  611.         TAG_DONE );
  612.  
  613.     ng.ng_LeftEdge += 130;
  614.     ng.ng_GadgetText = "FMove Child";
  615.     ng.ng_GadgetID++;
  616.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  617.         TAG_DONE );
  618.  
  619.     ng.ng_LeftEdge = 90;
  620.     ng.ng_TopEdge += 18;
  621.     ng.ng_UserData = 0;
  622.     ng.ng_GadgetText = "Home Parent";
  623.     ng.ng_GadgetID++;
  624.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  625.         TAG_DONE );
  626.  
  627.     ng.ng_LeftEdge += 130;
  628.     ng.ng_GadgetText = "Home Child";
  629.     ng.ng_GadgetID++;
  630.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  631.         TAG_DONE );
  632.  
  633.     if ( gad )
  634.     {
  635.         if ( panel_win = OpenWindowTags( NULL,
  636.         WA_Width, 640,
  637.         WA_Height, 105,
  638.         WA_Top, 11,
  639.         WA_Activate, TRUE,
  640.         WA_CloseGadget, TRUE,
  641.         WA_DragBar, TRUE,
  642.         WA_SizeGadget, TRUE,
  643.         WA_DepthGadget, TRUE,
  644.         WA_SimpleRefresh, TRUE,
  645.         WA_Title, "Control Panel",
  646.         WA_Gadgets, panel_gadgets,
  647.         WA_CustomScreen, panel_screen,
  648.         TAG_DONE ) )
  649.         {
  650.         /* whew! all is OK */
  651.         panel_win->UserPort = sharedport;
  652.         ModifyIDCMP( panel_win, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY |
  653.             CYCLEIDCMP | BUTTONIDCMP | IDCMP_REFRESHWINDOW );
  654.         GT_RefreshWindow( panel_win, NULL );
  655.         return( panel_win );
  656.         }
  657.         FreeGadgets( panel_gadgets );
  658.         panel_gadgets = NULL;
  659.     }
  660.     FreeVisualInfo( panel_vi );
  661.     panel_vi = NULL;
  662.     }
  663.     return( NULL );
  664. }
  665.  
  666. /*----------------------------------------------------------------------*/
  667.  
  668. void closePanel( void )
  669. {
  670.     if ( panel_win )
  671.     {
  672.     CloseWindowSafely( panel_win ); panel_win = NULL;
  673.     FreeGadgets( panel_gadgets ); panel_gadgets = NULL;
  674.     FreeVisualInfo( panel_vi ); panel_vi = NULL;
  675.     panel_screen = NULL;
  676.     }
  677. }
  678.  
  679. /*----------------------------------------------------------------------*/
  680.  
  681. struct Screen *findPanelScreen( void )
  682. {
  683.     struct Screen *sc;
  684.  
  685.     ULONG lock = LockIBase( NULL );
  686.     for ( sc = ((struct IntuitionBase *)IntuitionBase)->FirstScreen; sc; sc = sc->NextScreen )
  687.     {
  688.     if ( ( sc->UserData == CHILD_MAGIC ) || ( sc->UserData == PARENT_MAGIC ) )
  689.     {
  690.         break;
  691.     }
  692.     }
  693.     UnlockIBase( lock );
  694.     return( sc );
  695. }
  696.  
  697. /*----------------------------------------------------------------------*/
  698.  
  699. void handleGadget( struct Gadget *gad, UWORD code )
  700. {
  701.     BOOL undo = FALSE;    /* Set to true if gadget states need to be corrected */
  702.     BOOL rethinkp = FALSE;
  703.     BOOL rethinkc = FALSE;
  704.  
  705.     switch ( gad->GadgetID )
  706.     {
  707.     case GAD_PARENT_OPEN:
  708.         if ( !code )    /* request to close */
  709.         {
  710.         /* Only close parent if child still around */
  711.         if ( ( parent_sc ) && ( child_sc ) )
  712.         {
  713.             parent_desc.sd_Open = FALSE;
  714.             rethinkp = TRUE;
  715.         }
  716.         else
  717.         {
  718.             undo = TRUE;
  719.         }
  720.         }
  721.         else        /* request to open */
  722.         {
  723.         if ( !parent_sc )
  724.         {
  725.             parent_desc.sd_Open = TRUE;
  726.             rethinkp = TRUE;
  727.         }
  728.         }
  729.         break;
  730.  
  731.     case GAD_PARENT_LACE:
  732.         parent_desc.sd_Lace = code;
  733.         rethinkp = TRUE;
  734.         break;
  735.  
  736.     case GAD_PARENT_SIZE:
  737.         parent_desc.sd_Size = code;
  738.         rethinkp = TRUE;
  739.         break;
  740.  
  741.     case GAD_PARENT_DRAG:
  742.         parent_desc.sd_Drag = code;
  743.         rethinkp = TRUE;
  744.         break;
  745.  
  746.     case GAD_CHILD_OPEN:
  747.         if ( !code )    /* request to close */
  748.         {
  749.         /* Only close child if parent still around */
  750.         if ( ( child_sc ) && ( parent_sc ) )
  751.         {
  752.             child_desc.sd_Open = FALSE;
  753.             rethinkc = TRUE;
  754.         }
  755.         else
  756.         {
  757.             undo = TRUE;
  758.         }
  759.         }
  760.         else        /* request to open */
  761.         {
  762.         if ( !child_sc )
  763.         {
  764.             child_desc.sd_Open = TRUE;
  765.             rethinkc = TRUE;
  766.         }
  767.         }
  768.         break;
  769.  
  770.     case GAD_CHILD_LACE:
  771.         child_desc.sd_Lace = code;
  772.         rethinkc = TRUE;
  773.         break;
  774.  
  775.     case GAD_CHILD_SIZE:
  776.         child_desc.sd_Size = code;
  777.         rethinkc = TRUE;
  778.         break;
  779.  
  780.     case GAD_CHILD_DRAG:
  781.         child_desc.sd_Drag = code;
  782.         rethinkc = TRUE;
  783.         break;
  784.  
  785.     case GAD_FORWARD:
  786.     case GAD_BACK:
  787.     case GAD_CFORWARD:
  788.     case GAD_CBACK:
  789.         if ( child_sc )
  790.         {
  791.         /* The appropriate screen-depth code is in gad->UserData */
  792.         ScreenDepth( child_sc, ( ULONG )gad->UserData, NULL );
  793.         }
  794.         break;
  795.  
  796.     case GAD_MOVECHILD:
  797.     case GAD_FMOVECHILD:
  798.         if ( child_sc )
  799.         {
  800.         jiggleScreen( child_sc, ( gad->GadgetID == GAD_FMOVECHILD ) ?
  801.             SPOS_FORCEDRAG : 0 );
  802.         }
  803.         break;
  804.  
  805.     case GAD_MOVEPARENT:
  806.     case GAD_FMOVEPARENT:
  807.         if ( parent_sc )
  808.         {
  809.         jiggleScreen( parent_sc, ( gad->GadgetID == GAD_FMOVEPARENT ) ?
  810.             SPOS_FORCEDRAG : 0 );
  811.         }
  812.         break;
  813.  
  814.     case GAD_HOMEPARENT:
  815.         if ( parent_sc )
  816.         {
  817.         ScreenPosition( parent_sc, SPOS_ABSOLUTE, 0, 0, 0, 0 );
  818.         }
  819.         break;
  820.  
  821.     case GAD_HOMECHILD:
  822.         if ( child_sc )
  823.         {
  824.         ScreenPosition( child_sc, SPOS_ABSOLUTE, 0, 0, 0, 0 );
  825.         }
  826.         break;
  827.     }
  828.     if ( rethinkp )
  829.     {
  830.     if ( parent_sc )
  831.     {
  832.         parent_desc.sd_Top = parent_sc->TopEdge;
  833.         if ( parent_desc.sd_IsLace )
  834.         {
  835.         parent_desc.sd_Top /= 2;
  836.         }
  837.         parent_sc = closeMyScreen( parent_sc );
  838.     }
  839.     if ( parent_desc.sd_Open )
  840.     {
  841.         parent_sc = openMyScreen( TRUE );
  842.         parent_desc.sd_IsLace = parent_desc.sd_Lace;
  843.     }
  844.     }
  845.  
  846.     if ( rethinkc )
  847.     {
  848.     if ( child_sc )
  849.     {
  850.         child_desc.sd_Top = child_sc->TopEdge;
  851.         if ( child_desc.sd_IsLace )
  852.         {
  853.         child_desc.sd_Top /= 2;
  854.         }
  855.         child_sc = closeMyScreen( child_sc );
  856.     }
  857.     if ( child_desc.sd_Open )
  858.     {
  859.         child_sc = openMyScreen( FALSE );
  860.         child_desc.sd_IsLace = child_desc.sd_Lace;
  861.     }
  862.     }
  863.  
  864.     if ( undo && panel_win )
  865.     {
  866.     int i;
  867.     for ( i = 0; i < NUM_SETTABLE; i++ )
  868.     {
  869.         LONG *longptr;
  870.         if ( longptr = mygad[ i ]->UserData )
  871.         {
  872.         GT_SetGadgetAttrs( mygad[ i ], panel_win, NULL,
  873.             GTCY_Active, *longptr,
  874.             TAG_DONE );
  875.         }
  876.     }
  877.     }
  878.  
  879.     if ( ( !panel_win ) || ( panel_win->WScreen != findPanelScreen() ) )
  880.     {
  881.     closePanel();
  882.     openPanel();
  883.     }
  884. }
  885.  
  886. /*----------------------------------------------------------------------*/
  887.  
  888. void jiggleScreen( struct Screen *sc, ULONG flags )
  889. {
  890.     LONG i, step;
  891.  
  892.     step = 2;
  893.     for ( i = 0; i < 40; i++ )
  894.     {
  895.     ScreenPosition( sc, flags, 0, step, 0, 0 );
  896.     if ( i == 9 )
  897.     {
  898.         step = -2;
  899.     }
  900.     else if ( i == 29 )
  901.     {
  902.         step = 2;
  903.     }
  904.     }
  905.     step = -2;
  906.     for ( i = 0; i < 40; i++ )
  907.     {
  908.     ScreenPosition( sc, flags, step, 0, 0, 0 );
  909.     if ( i == 19 )
  910.     {
  911.         step = 2;
  912.     }
  913.     }
  914. }
  915.  
  916. /*----------------------------------------------------------------------*/
  917.